package com.dreamlike.demo.HttpUtil.Core.ResponseBodyHandler;

import com.dreamlike.demo.HttpUtil.Core.HttpDefinition;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

//有很多检查地方可以缓存
public class UrlencodedResponseBodyHandler implements StringResponseBodyHandler<Object> {

    @Override
    public Object trans(HttpDefinition httpDefinition, String body) {
        Method method = httpDefinition.getMethod();
        if (Map.class.isAssignableFrom(method.getReturnType())){
            return transToMap(body);
        }else {
         return transToObject(httpDefinition.getMethod(), body);
        }
    }
    //todo 目前只考虑不重复的情况
    private Map<String,String> transToMap(String body){
        System.out.println(body);
        return Arrays.stream(body.split("&"))
                .map(s -> s.split("="))
                .collect(Collectors.toMap(s -> s[0], s -> s[1],(s1,s2) -> s2));
    }
    //单层泛型
    @SneakyThrows
    private Object transToObject(Method method, String body){
        Class actualType;
        if (Future.class.isAssignableFrom(method.getReturnType())) {
            actualType = ((Class) ((ParameterizedType) method.getGenericReturnType())
                    .getActualTypeArguments()[0]);
        }else {
            actualType = method.getReturnType();
        }
        Map<String, String> params = transToMap(body);
        Object instance = actualType.getConstructor().newInstance();
        Arrays.stream(actualType.getDeclaredFields())
                .filter(f -> params.containsKey(f.getName()))
                .forEach(f -> setField(f,params.get(f.getName()), instance));
        return instance;
    }
    @SneakyThrows
    public void setField(Field field,String s,Object target){
        Class<?> type = field.getType();
        if (!isNormalType(type)) {
            throw new RuntimeException(field+"非八大类型或String");
        }
        field.setAccessible(true);
        if (type.equals(String.class)) {
           field.set(target,s);
            return;
        }
        if(type.equals(int.class)||type.equals(Integer.class)){
            field.set(target,Integer.valueOf(s));
            return;
        }
        if(type.equals(long.class)||type.equals(Long.class)){
            field.set(target,Long.valueOf(s));
            return;
        }
        if(type.equals(short.class)||type.equals(Short.class)){
            field.set(target,Short.valueOf(s));
            return;
        }
        if(type.equals(byte.class)||type.equals(Byte.class)){
            field.set(target,Byte.valueOf(s));
            return;
        }
        if(type.equals(char.class)||type.equals(Character.class)){
            field.set(target, s.charAt(0));
            return;
        }
        if(type.equals(double.class)||type.equals(Double.class)){
            field.set(target,Double.valueOf(s));
            return;
        }
        if(type.equals(float.class)||type.equals(Float.class)){
            field.set(target,Float.valueOf(s));
            return;
        }
        if(type.equals(boolean.class)||type.equals(Boolean.class)){
            field.set(target,Boolean.valueOf(s));
            return;
        }
    }
    public boolean isNormalType(Class c){
        return c.isPrimitive() || c.equals(String.class)
                || c.equals(Integer.class)
                || c.equals(Long.class)
                || c.equals(Double.class)
                || c.equals(Float.class)
                || c.equals(Byte.class)
                || c.equals(Character.class)
                || c.equals(Boolean.class)
                || c.equals(Short.class);
    }

}
